/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	Bloom:		GlbCode.cpp			*/
/********************************************************/

#include "GlbCode.h"

int GlbCodeConvert(char* pszFm, char* pszTo, char* pszSrc, int iSrc, char* pszDst, int iDst)
{
	iconv_t iConv;
	char** pszIn = &pszSrc;
	char** pszOut = &pszDst;
	int iReturn = GLB_SUCCESS;

	if ((iconv_t)GLB_FAILURE != (iConv = iconv_open(pszTo, pszFm))) {
		if (GLB_FAILURE == iconv(iConv, pszIn, (size_t*)&iSrc, pszOut, (size_t*)&iDst)) {
			GLB_ERROR("%s\n", strerror(errno));
			iReturn = GLB_FAILURE;
		}
		iconv_close(iConv);
	}
	else {
		GLB_ERROR("%s\n", strerror(errno));
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

char* GlbCodeChineseToGB2312(char* pszChinese)
{
	int iWord = 0;
	int iCount = 0;
	int iGB2312 = 0;
	char szTemp[4] = { 0 };
	char* pszGB2312 = NULL;

	iWord = strlen(pszChinese);
	iGB2312 = (((iWord % 2) ? ((iWord / 2) + 2) : (iWord / 2)) * 6) + 2;
	if (NULL != (pszGB2312 = (char*)malloc(sizeof(char) * iGB2312))) {
		memset(pszGB2312, '\0', iGB2312);
		for (iCount = 0; iCount < iWord; iCount ++) {
			if (0 != isalnum((UCHAR)pszChinese[iCount])) {
				sprintf(szTemp, "%c", pszChinese[iCount]);
				strcat(pszGB2312, szTemp);
			}
			else if (0 != isspace((UCHAR)pszChinese[iCount])) {
				strcat(pszGB2312, "+");
			}
			else {
				sprintf(szTemp, "%%%X%X", ((UCHAR*)pszChinese)[iCount] >> 4, ((UCHAR*)pszChinese)[iCount] % 16);
				strcat(pszGB2312, szTemp);
			}
			memset(szTemp, '\0', sizeof(szTemp));
		}
	}

	return pszGB2312;
}

char* GlbCodeGB2312ToChinese(char* pszGB2312)
{
	int iCount = 0;
	int iOffset = 0;
	int iGB2312 = 0;
	char* pszChinese = NULL;
	char szTemp[2] = { 0 };
	
	iGB2312 = strlen(pszGB2312);
	if (NULL != (pszChinese = (char*)malloc(sizeof(char) * iGB2312 + 1))) {
		memset(pszChinese, '\0', iGB2312 + 1);
		while (iCount < iGB2312) {
			if ('%' == *(pszGB2312 + iCount)) {
				szTemp[0] = *(pszGB2312 + iCount + 1);
				szTemp[1] = *(pszGB2312 + iCount + 2);
				sprintf(pszChinese + iOffset, "%c", GlbCodeStrToBin(szTemp));
				iCount += 3;
				iOffset ++;
			}
			else if ('+' == *(pszGB2312 + iCount)) {
				sprintf(pszChinese + iOffset, " ");
				iOffset ++;
				iCount ++;
			}
			else {
				memset(szTemp, '\0', sizeof(szTemp));
				sprintf(pszChinese + iOffset, "%c", *(pszGB2312 + iCount));
				iOffset ++;
				iCount ++;
			}
			memset(szTemp, '\0', sizeof(szTemp));
		}
	}

	return pszChinese;
}

char* GlbCodeChineseToUTF8(char* pszChinese)
{
	int iTemp = 0;
	int iChinese = 0;
	UINT uiCount = 0;
	char* pszTemp = NULL;
	char* pszUTF8 = NULL;
	char szTemp[4] = { 0 };

	iChinese = strlen(pszChinese);
	iTemp = (((iChinese % 2) ? ((iChinese / 2) + 2) : (iChinese / 2)) * 9) + 2;
	if (NULL != (pszTemp = (char*)malloc(sizeof(char) * iTemp))) {
		memset(pszTemp, '\0', iTemp);
		GlbCodeConvert((char*)"gb2312", (char*)"utf-8", pszChinese, iChinese, pszTemp, iTemp);
		if (NULL != (pszUTF8 = (char*)malloc(sizeof(char) * iTemp))) {
			memset(pszUTF8, '\0', iTemp);
			for (uiCount = 0; uiCount < strlen(pszTemp); uiCount ++) {
				if (0 != isalnum((UCHAR)(*(pszTemp + uiCount)))) {
					sprintf(szTemp, "%c", (UCHAR)(*(pszTemp + uiCount)));
					strcat(pszUTF8, szTemp);
				}
				else if (0 != isspace((UCHAR)(*(pszTemp + uiCount)))) {
					strcat(pszUTF8, "+");
				}
				else {
					sprintf(szTemp, "%%%X%X", (UCHAR)(*(pszTemp + uiCount)) >> 4, (UCHAR)(*(pszTemp + uiCount)) % 16);
					strcat(pszUTF8, szTemp);
				}
				memset(szTemp, '\0', sizeof(szTemp));
			}
		}
		free(pszTemp);
	}

	return pszUTF8;
}

char* GlbCodeUTF8ToChinese(char* pszUTF8)
{
	int iChinese = 0;
	char* pszTemp = NULL;
	char* pszChinese = NULL;

	iChinese = strlen(pszUTF8) * 2;
	if (NULL != (pszTemp = GlbCodeGB2312ToChinese(pszUTF8))) {
		if (NULL != (pszChinese = (char*)malloc(sizeof(char) * iChinese + 1))) {
			memset(pszChinese, '\0', iChinese + 1);
			GlbCodeConvert((char*)"utf-8", (char*)"gb2312", pszTemp, strlen(pszTemp), pszChinese, iChinese);
		}
		free(pszTemp);
	}

	return pszChinese;
}

char GlbCodeCharToInt(char ch)
{
	if (ch >= '0' && ch <= '9') return (char)(ch - '0');
	if (ch >= 'a' && ch <= 'f') return (char)(ch - 'a' + 10);
	if (ch >= 'A' && ch <= 'F') return (char)(ch - 'A' + 10);

	return (char)(-1);
}

char GlbCodeStrToBin(char* pszWord)
{
	char cReturn = '\0';
	char szTemp[2] = { 0 };

	szTemp[0] = GlbCodeCharToInt(pszWord[0]);
	szTemp[1] = GlbCodeCharToInt(pszWord[1]);

	cReturn = (szTemp[0] << 4) | szTemp[1];

	return cReturn;
}
